home *** CD-ROM | disk | FTP | other *** search
/ Software Vault: The Gold Collection / Software Vault - The Gold Collection (American Databankers) (1993).ISO / cdr49 / 115_01.zip / C80LIB < prev    next >
Text File  |  1993-06-01  |  19KB  |  1,241 lines

  1. #asm
  2. ;
  3. ;
  4. ;------------------------------------------------------------------
  5. ;    Small-C  Run-time Library
  6. ;
  7. ;
  8. ;    V3b    As of June 9, 1980 12pm (rj)
  9. ;           corrected cp to chp in @gets
  10. ;           changed lower case to hex constants in @fopen and fcb
  11. ;    V4    As of June 26, 1980 12:15pm (gtf)
  12. ;           Changed all @'s and ?'s to "QZ" for ASM compatibility
  13. ;    V4b    As of July 7, 1980 3:00 pm (gtf)
  14. ;              Changed putc() to test code returned by cput()
  15. ;    V4c    As of July 9, 1980 9:15 pm (gtf)
  16. ;           Fixed bug in CPMIO which returned wrong error status.
  17. ;           Added PUTS() function
  18. ;           Un-hardwired I/O buffer count.
  19. ;           Made GETCHAR() print LF after reading CR.
  20. ;           Made GETCHAR() return -1 on EOF (=CTRL-Z)
  21. ;           Added EOL and LF equates, instead of magic numbers
  22. ;    V4d    As of July 16, 1980  9:00 pm (gtf)
  23. ;           Added EXIT() function
  24. ;------------------------------------------------------------------
  25. ;
  26. ; Runtime library initialization.  Set up default drive for CP/M.
  27. CCGO:    MVI    C,QUERY        ;get logged-in disk
  28.     CALL    BDOS
  29.     INR    A        ;make it so it will work in fcb
  30.     STA    DFLTDSK
  31.     RET
  32. ;Fetch a single byte from the address in HL and
  33. ; sign extend into HL
  34. CCGCHAR: MOV    A,M
  35. CCSXT:    MOV    L,A
  36.     RLC
  37.     SBB    A
  38.     MOV    H,A
  39.     RET
  40. ;Fetch a full 16-bit integer from the address in HL
  41. CCGINT:    MOV    A,M
  42.     INX    H
  43.     MOV    H,M
  44.     MOV    L,A
  45.     RET
  46. ;Store a single byte from HL at the address in DE
  47. CCPCHAR: MOV    A,L
  48.     STAX    D
  49.     RET
  50. ;Store a 16-bit integer in HL at the address in DE
  51. CCPINT:    MOV    A,L
  52.     STAX    D
  53.     INX    D
  54.     MOV    A,H
  55.     STAX    D
  56.     RET
  57. ;Inclusive "or" HL and DE into HL
  58. CCOR:    MOV    A,L
  59.     ORA    E
  60.     MOV    L,A
  61.     MOV    A,H
  62.     ORA    D
  63.     MOV    H,A
  64.     RET
  65. ;Exclusive "or" HL and DE into HL
  66. CCXOR:    MOV    A,L
  67.     XRA    E
  68.     MOV    L,A
  69.     MOV    A,H
  70.     XRA    D
  71.     MOV    H,A
  72.     RET
  73. ;"And" HL and DE into HL
  74. CCAND:    MOV    A,L
  75.     ANA    E
  76.     MOV    L,A
  77.     MOV    A,H
  78.     ANA    D
  79.     MOV    H,A
  80.     RET
  81. ;Test if HL = DE and set HL = 1 if true else 0
  82. CCEQ:    CALL    CCCMP
  83.     RZ
  84.     DCX    H
  85.     RET
  86. ;Test if DE ~= HL
  87. CCNE:    CALL    CCCMP
  88.     RNZ
  89.     DCX    H
  90.     RET
  91. ;Test if DE > HL (signed)
  92. CCGT:    XCHG
  93.     CALL    CCCMP
  94.     RC
  95.     DCX    H
  96.     RET
  97. ;Test if DE <= HL (signed)
  98. CCLE:    CALL    CCCMP
  99.     RZ
  100.     RC
  101.     DCX    H
  102.     RET
  103. ;Test if DE >= HL (signed)
  104. CCGE:    CALL    CCCMP
  105.     RNC
  106.     DCX    H
  107.     RET
  108. ;Test if DE < HL (signed)
  109. CCLT:    CALL    CCCMP
  110.     RC
  111.     DCX    H
  112.     RET
  113. ;Common routine to perform a signed compare
  114. ; of DE and HL
  115. ;This routine performs DE - HL and sets the conditions:
  116. ;    Carry reflects sign of difference (set means DE < HL)
  117. ;    Zero/non-zero set according to equality.
  118. CCCMP:    MOV    A,E
  119.     SUB    L
  120.     MOV    E,A
  121.     MOV    A,D
  122.     SBB    H
  123.     LXI    H,1    ;preset true condition
  124.     JM    CCCMP1
  125.     ORA    E    ;"OR" resets carry
  126.     RET
  127. CCCMP1:    ORA    E
  128.     STC        ;set carry to signal minus
  129.     RET
  130. ;
  131. ;Test if DE >= HL (unsigned)
  132. CCUGE:    CALL    CCUCMP
  133.     RNC
  134.     DCX    H
  135.     RET    
  136. ;
  137. ;Test if DE < HL (unsigned)
  138. CCULT:    CALL    CCUCMP
  139.     RC
  140.     DCX    H
  141.     RET
  142. ;
  143. ;Test if DE > HL (unsigned)
  144. CCUGT:    XCHG
  145.     CALL    CCUCMP
  146.     RC
  147.     DCX    H
  148.     RET
  149. ;
  150. ;Test if DE <= HL (unsigned)
  151. CCULE:    CALL    CCUCMP
  152.     RZ
  153.     RC
  154.     DCX    H
  155.     RET
  156. ;
  157. ;Common routine to perform unsigned compare
  158. ;carry set if DE < HL
  159. ;zero/nonzero set accordingly
  160. CCUCMP:    MOV    A,D
  161.     CMP    H
  162.     JNZ    $+5
  163.     MOV    A,E
  164.     CMP    L
  165.     LXI    H,1
  166.     RET
  167. ;
  168. ;Shift DE arithmetically right by HL and return in HL
  169. CCASR:    XCHG
  170.     MOV    A,H
  171.     RAL
  172.     MOV    A,H
  173.     RAR
  174.     MOV    H,A
  175.     MOV    A,L
  176.     RAR
  177.     MOV    L,A
  178.     DCR    E
  179.     JNZ    CCASR+1
  180.     RET
  181. ;Shift DE arithmetically left by HL and return in HL
  182. CCASL:    XCHG
  183.     DAD    H
  184.     DCR    E
  185.     JNZ    CCASL+1
  186.     RET
  187. ;Subtract HL from DE and return in HL
  188. CCSUB:    MOV    A,E
  189.     SUB    L
  190.     MOV    L,A
  191.     MOV    A,D
  192.     SBB    H
  193.     MOV    H,A
  194.     RET
  195. ;Form the two's complement of HL
  196. CCNEG:    CALL    CCCOM
  197.     INX    H
  198.     RET
  199. ;Form the one's complement of HL
  200. CCCOM:    MOV    A,H
  201.     CMA
  202.     MOV    H,A
  203.     MOV    A,L
  204.     CMA
  205.     MOV    L,A
  206.     RET
  207. ;Multiply DE by HL and return in HL
  208. CCMULT:    MOV    B,H
  209.     MOV    C,L
  210.     LXI    H,0
  211. CCMULT1: MOV    A,C
  212.     RRC
  213.     JNC    $+4
  214.     DAD    D
  215.     XRA    A
  216.     MOV    A,B
  217.     RAR
  218.     MOV    B,A
  219.     MOV    A,C
  220.     RAR
  221.     MOV    C,A
  222.     ORA    B
  223.     RZ
  224.     XRA    A
  225.     MOV    A,E
  226.     RAL
  227.     MOV    E,A
  228.     MOV    A,D
  229.     RAL
  230.     MOV    D,A
  231.     ORA    E
  232.     RZ
  233.     JMP    CCMULT1
  234. ;Divide DE by HL and return quotient in HL, remainder in DE
  235. CCDIV:    MOV    B,H
  236.     MOV    C,L
  237.     MOV    A,D
  238.     XRA    B
  239.     PUSH    PSW
  240.     MOV    A,D
  241.     ORA    A
  242.     CM    CCDENEG
  243.     MOV    A,B
  244.     ORA    A
  245.     CM    CCBCNEG
  246.     MVI    A,16
  247.     PUSH    PSW
  248.     XCHG
  249.     LXI    D,0
  250. CCDIV1:    DAD    H
  251.     CALL    CCRDEL
  252.     JZ    CCDIV2
  253.     CALL    CCCMPBCDE
  254.     JM    CCDIV2
  255.     MOV    A,L
  256.     ORI    1
  257.     MOV    L,A
  258.     MOV    A,E
  259.     SUB    C
  260.     MOV    E,A
  261.     MOV    A,D
  262.     SBB    B
  263.     MOV    D,A
  264. CCDIV2:    POP    PSW
  265.     DCR    A
  266.     JZ    CCDIV3
  267.     PUSH    PSW
  268.     JMP    CCDIV1
  269. CCDIV3:    POP    PSW
  270.     RP
  271.     CALL    CCDENEG
  272.     XCHG
  273.     CALL    CCDENEG
  274.     XCHG
  275.     RET
  276. CCDENEG: MOV    A,D
  277.     CMA
  278.     MOV    D,A
  279.     MOV    A,E
  280.     CMA
  281.     MOV    E,A
  282.     INX    D
  283.     RET
  284. CCBCNEG: MOV    A,B
  285.     CMA
  286.     MOV    B,A
  287.     MOV    A,C
  288.     CMA
  289.     MOV    C,A
  290.     INX    B
  291.     RET
  292. CCRDEL:    MOV    A,E
  293.     RAL
  294.     MOV    E,A
  295.     MOV    A,D
  296.     RAL
  297.     MOV    D,A
  298.     ORA    E
  299.     RET
  300. CCCMPBCDE: MOV    A,E
  301.     SUB    C
  302.     MOV    A,D
  303.     SBB    B
  304.     RET
  305. ;
  306. ; ========================================
  307. ;  I/O subroutines for CP/M
  308. ;      By Glen Fisher
  309. ;       The Code Works(tm)
  310. ; ========================================
  311. ;
  312. NULL    EQU    0    ;pointer to nothing
  313. FCBSIZE    EQU    36    ;size, in bytes, of an FCB
  314. NEXTP    EQU    0    ;offset to next-character pointer in I/O structure
  315. UNUSED    EQU    2    ;offset to unused-positions-count in I/O structure
  316. BUFFER    EQU    4    ;offset to disk sector buffer in I/O structure
  317. FLAG    EQU    33    ;file-type flag byte (in unused part of FCB)
  318. FREEFLG    EQU    128    ;This I/O structure is available for the taking
  319. EOFFLG    EQU    2    ;The end of this file has been hit
  320. WRTFLG    EQU    1    ;This file open for writing
  321. BUFSIZ    EQU    128    ;how long the sector buffer is
  322. NBUFS    EQU    4    ;number of I/O buffers (change buffer declarations, too)
  323.     ; CP/M system call codes
  324. CLOSE    EQU    16    ;close a file
  325. CREATE    EQU    22    ;make a file
  326. DMA    EQU    26    ;set DMA (I/O address)
  327. DELETE    EQU    19    ;delete a file
  328. GETCH    EQU    1    ;read character from console
  329. GETSTR    EQU    10    ;read string from console
  330. OPEN    EQU    15    ;open a file
  331. PUTCH    EQU    2    ;write character to console
  332. QUERY    EQU    25    ;get logged-in drive id
  333. READ    EQU    20    ;read a sector
  334. SELECT    EQU    14    ;log-in a drive
  335. WRITE    EQU    21    ;write a sector
  336. LF    EQU    10    ;line feed
  337. EOL    EQU    13    ;end-of-line character (=carriage return)
  338. CTRLZ    EQU    26    ;end-of-file mark for text files
  339. TBUFF    EQU    80H    ;address of default I/O address
  340. DFLTDSK    DS    1    ;drive to use if no drive is named
  341. UNIT    DS    2    ;I/O structure address to act on
  342. IP    DS    2    ;int *ip;
  343. CHP    DS    2    ;char *chp;
  344. DP    DS    2    ;char *dp;
  345. FILE    DS    2    ;file name
  346. MODE    DS    2    ;char *mode;(read or write)
  347. ZCH    DS    2    ;char ch;
  348. ZT    DS    2    ;int t;
  349. FN    DS    2    ;int fn;    i/o function (for cpmio)
  350. ;
  351. ;    exit()
  352. ;
  353. ;    Stop execution of the program,
  354. ;    restore the logged-in drive,
  355. ;    and re-boot CP/M
  356. ;
  357. QZEXIT:
  358.     LDA    DFLTDSK        ; Grab orig. logged-in disk
  359.     MOV    E,A
  360.     DCR    E        ; (cvt. back to 0-n)
  361.     MVI    C,SELECT    ; and log it in again
  362.     CALL    BDOS
  363.     JMP    0        ; Our work is complete.
  364. ;
  365. ;    cpm(bc,de)
  366. ;
  367. ;    fill BC and DE, and then call CP/M
  368. ;
  369. ;    return whatever is in A
  370. ;
  371. BDOS    EQU    5
  372.  
  373. QZCPM:
  374.     POP    H    ;grab the arguments
  375.     POP    D
  376.     POP    B
  377.     PUSH    B    ;restore the size of the stack
  378.     PUSH    D
  379.     PUSH    H
  380.     CALL    BDOS    ;go to daddy
  381.     JMP    CCSXT    ;hand the answer back
  382. ;
  383. ;    grabio()
  384. ;
  385. ;    find an input buffer, and return its address.
  386. ;    if there isn't one, return a NULL.
  387. ;
  388. GRABIO:                            ;6 May 80 rj
  389.     MVI    B,NBUFS
  390.     LXI    H,IOBUFS+FLAG
  391.     LXI    D,FCBSIZE+BUFFER+BUFSIZ
  392.     MVI    A,FREEFLG
  393.  
  394. GRAB2:    CMP    M            ;flag byte == freeflg?
  395.     JZ    GRAB3            ;if so, found a free buffer
  396.     DAD    D            ;on to next buffer
  397.     DCR    B
  398.     JNZ    GRAB2            ;if there is one...
  399.     LXI    H,NULL            ;there ain't
  400.     RET                ;give up
  401.  
  402. GRAB3:    MVI    M,0            ;mark buffer as taken
  403.     LXI    D,-FLAG            ;back up to buffer start
  404.     DAD    D     
  405.     RET                ;and hand it back
  406. ;
  407. ;    freeio(unit)
  408. ;
  409. ;    mark a buffer as free.
  410. ;
  411. FREEIO:                    ;Mod  6 May 80 rj
  412.     POP    B            ;save rtn addr
  413.     POP    H            ;get buffer addr
  414.     PUSH    H            ;put the stack back together
  415.     PUSH    B
  416.     LXI    D,FLAG            ;find flag byte
  417.     DAD    D
  418.     MVI    M,FREEFLG        ;mark buffer as 'free'
  419.     LXI    H,NULL            ;return something
  420.     RET
  421.  
  422. IOBUFS:
  423.     DS    FCBSIZE-3
  424.     DB    FREEFLG,0,0
  425.     DS    BUFFER+BUFSIZ
  426.  
  427.     DS    FCBSIZE-3
  428.     DB    FREEFLG,0,0
  429.     DS    BUFFER+BUFSIZ
  430.  
  431.     DS    FCBSIZE-3
  432.     DB    FREEFLG,0,0
  433.     DS    BUFFER+BUFSIZ
  434.  
  435.     DS    FCBSIZE-3        ;mod 4 May 80 rj
  436.     DB    FREEFLG,0,0
  437.     DS    BUFFER+BUFSIZ
  438. ;
  439. ;    fopen(name,mode)
  440. ;
  441. QZFOPEN:
  442.     POP    B            ;get args
  443.     POP    H            ;mode
  444.     SHLD    MODE
  445.     POP    D
  446.     XCHG
  447.     SHLD    FILE
  448.     PUSH    H
  449.     PUSH    D
  450.     PUSH    B
  451.     CALL    GRABIO            ; unit = grabio();
  452.     SHLD    UNIT
  453.     MOV    A,H            ; if(unit==NULL)
  454.     ORA    L            ;    return(NULL);
  455.     RZ
  456.     LXI    D,FCBSIZE        ; ip = unit+FCBSIZE;
  457.     DAD    D
  458.     SHLD    IP
  459.     LHLD    IP            ; ip[NEXTP] = &ip[BUFFER];
  460.     LXI    D,BUFFER
  461.     DAD    D
  462.     XCHG
  463.     LHLD    IP
  464.     LXI    B,NEXTP
  465.     DAD    B
  466.     MOV    M,E
  467.     INX    H
  468.     MOV    M,D
  469.  
  470.     LHLD    UNIT             ; fcb(unit,name);
  471.     PUSH    H
  472.     LHLD    FILE
  473.     PUSH    H
  474.     CALL    FCB
  475.     POP    H
  476.     POP    H
  477.  
  478.     LHLD    UNIT            ; cpmdisk(*unit);
  479.     MOV    L,M
  480.     MVI    H,0
  481.     PUSH    H
  482.     CALL    CPMDISK
  483.     POP    H
  484.  
  485.     LHLD    MODE            ; if(*mode=='r'  || *mode=='R'){
  486.     MOV    A,M
  487.     CPI    72H                     ; 'r' ? 9 Jun 80 rj
  488.     JZ    FOPIF0
  489.     CPI    52H            ; 'R' ? 9 Jun 80 rj
  490.     JNZ    FOPIF1
  491. FOPIF0:
  492.     MVI    C,OPEN            ;    if(cpm(OPEN,unit)<0){
  493.     LHLD    UNIT
  494.     XCHG
  495.     CALL    BDOS
  496.     ORA    A
  497.     JP    FOPIF2
  498.  
  499.     LHLD    UNIT            ;        freeio(unit);
  500.     PUSH    H
  501.     CALL    FREEIO
  502.     POP    H
  503.  
  504.     LXI    H,NULL            ;        return(NULL);
  505.     RET
  506.                     ;        }
  507. FOPIF2:
  508.     LHLD    IP            ;    ip[UNUSED] = 0;
  509.     LXI    D,UNUSED
  510.     DAD    D
  511.     LXI    D,0
  512.     MOV    M,E
  513.     INX    H
  514.     MOV    M,D
  515.                        ;    }
  516.     JMP    FOPIF4
  517. FOPIF1:                    ; else if(*mode=='w' || *mode=='W'){
  518.     LHLD    MODE    
  519.     MOV    A,M
  520.     CPI    77H            ; 'w'  9 Jun 80 rj
  521.     JZ    FOPIF1A
  522.     CPI    57H            ; 'W'  9 Jun 80 rj
  523.     JNZ    FOPIF5
  524. FOPIF1A:
  525.     MVI    C,DELETE        ;    cpm(DELETE,unit);
  526.     LHLD    UNIT
  527.     XCHG
  528.     CALL    BDOS
  529.  
  530.     MVI    C,CREATE        ;    if(cpm(CREATE,unit)<0){
  531.     LHLD    UNIT
  532.     XCHG
  533.     CALL    BDOS
  534.     ORA    A
  535.     JP    FOPIF3
  536.  
  537.     LHLD    UNIT            ;        freeio(unit);
  538.     PUSH    H
  539.     CALL    FREEIO
  540.     POP    H
  541.  
  542.     LXI    H,NULL            ;        return(NULL);
  543.     RET
  544.                     ;        }
  545. FOPIF3:
  546.     LHLD    IP            ;    ip[UNUSED] = BUFSIZ;
  547.     LXI    D,UNUSED
  548.     DAD    D
  549.     LXI    D,BUFSIZ
  550.     MOV    M,E
  551.     INX    H
  552.     MOV    M,D
  553.  
  554.     LHLD    UNIT            ;    unit[FLAG] = WRITE_FL;
  555.     LXI    D,FLAG
  556.     DAD    D
  557.     MVI    A,WRTFLG
  558.     ORA    M
  559.     MOV    M,A
  560.     JMP    FOPIF4
  561.                     ;    }
  562. FOPIF5:
  563.     LHLD    UNIT            ; else{    freeio(unit);
  564.     PUSH    H
  565.     CALL    FREEIO
  566.     POP    H
  567.  
  568.     LXI    H,NULL            ;    return(NULL);
  569.     RET
  570.                     ;    }
  571. FOPIF4:
  572.     LHLD    UNIT            ; return(unit);
  573.     RET
  574. ;
  575. ;    fclose(unit)
  576. ;
  577. QZFCLOSE:
  578.     POP    B
  579.     POP    H
  580.     SHLD    UNIT
  581.     PUSH    H
  582.     PUSH    B
  583.  
  584.     LXI    H,1            ; t = 1;
  585.     SHLD    ZT
  586.  
  587.     LHLD    UNIT            ; if(unit[FLAG] & WRITE_FL){
  588.     LXI    D,FLAG
  589.     DAD    D
  590.     MOV    A,M
  591.     ANI    WRTFLG
  592.     JZ    FCLIF1
  593.  
  594.     LXI    H,CTRLZ            ;    putc(CTRL_Z,unit);    
  595.     PUSH    H
  596.     LHLD    UNIT
  597.     PUSH    H
  598.     CALL    QZPUTC
  599.     POP    H
  600.     POP    H
  601.  
  602.     LHLD    UNIT            ;    ip = unit + FCBSIZE;
  603.     LXI    D,FCBSIZE
  604.     DAD    D
  605.     SHLD    IP
  606.  
  607.     LHLD    IP            ;        cp = ip[NEXTP];
  608.     LXI    D,NEXTP
  609.     DAD    D
  610.     MOV    E,M
  611.     INX    H
  612.     MOV    D,M
  613.     XCHG
  614.     SHLD    CHP
  615.  
  616.     LHLD    IP            ;        dp = &ip[BUFFER]+BUFSIZ;
  617.     LXI    D,BUFFER+BUFSIZ
  618.     DAD    D
  619.     SHLD    DP
  620.  
  621. FCLWH1:                    ;        while(cp<dp)
  622.     LHLD    CHP
  623.     XCHG
  624.     LHLD    DP
  625.     MOV    A,D
  626.     CMP    H
  627.     JC    FCLWH2
  628.     JNZ    FCLWH3
  629.     MOV    A,E
  630.     CMP    L
  631.     JNC    FCLWH3
  632. FCLWH2:                    ;            *cp++ = CTRL_Z;
  633.     LHLD    CHP
  634.     MVI    M,CTRLZ
  635.     INX    H
  636.     SHLD    CHP
  637.     JMP    FCLWH1
  638. FCLWH3:
  639.     LXI    H,WRITE            ;        if(cpmio(WRITE,unit)<0)
  640.     PUSH    H
  641.     LHLD    UNIT
  642.     PUSH    H
  643.     CALL    CPMIO
  644.     POP    D
  645.     POP    D
  646.     MOV    A,H
  647.     ORA    A
  648.     JP    FCLIF4
  649.  
  650.     LXI    H,0            ;            t = 0;
  651.     SHLD    ZT
  652. FCLIF4:
  653.                     ;        }
  654. FCLIF3:
  655.                     ;    }
  656. FCLIF1:
  657.     MVI    C,CLOSE            ; if(cpm(CLOSE,unit)<0)
  658.     LHLD    UNIT
  659.     XCHG
  660.     CALL    BDOS
  661.     ORA    A
  662.     JP    FCLIF5
  663.  
  664.     LXI    H,0            ;    t = 0;
  665.     SHLD    ZT
  666. FCLIF5:
  667.     LHLD    UNIT             ; freeio(unit);
  668.     PUSH    H
  669.     CALL    FREEIO
  670.     POP    H
  671.  
  672.     LHLD    ZT            ; return(NULL+t);
  673.     RET
  674. ;
  675. ;    fcb(fp,name)
  676. ;
  677. FCB:
  678.     POP    H            ;get args
  679.     POP    D            ;name
  680.     POP    B            ;fp
  681.     PUSH    B
  682.     PUSH    D
  683.     PUSH    H
  684.  
  685.     INX    D            ; if(name[1]==':'){
  686.     LDAX    D
  687.     DCX    D
  688.     CPI    ':'
  689.     JNZ    FCBIF1
  690.  
  691.     LDAX    D            ;    A = *name - '@';
  692.     SUI    40H            ; '@' 9 Jun 80 rj
  693.          
  694.     INX    D            ;    name += 2;
  695.     INX    D
  696.     
  697.       CPI    61H-41H            ;    if(A>'a'-'A') /* lower case? */  9 Jun 80 rj
  698.        JC     FCBIF2
  699.       SUI    61H-41H            ;        A -= 'a'-'A'; 9 Jun 80 rj
  700.  
  701.     JMP    FCBIF2            ;    }
  702. FCBIF1:
  703.     LDA    DFLTDSK            ; else    A = default_drive;
  704. FCBIF2:
  705.     STAX    B            ; *fp++ = A;
  706.     INX    B
  707.  
  708.     MVI    H,' '            ; fp = fcbfill(fp,name,' ',8);
  709.     MVI    L,8
  710.     CALL    FCBFILL
  711.  
  712.     MVI    L,3            ; fp = fcbfill(fp,name,' ',3);
  713.     CALL    FCBFILL
  714.  
  715.     MVI    H,0            ; fp = fcbpad(fp,0,4);
  716.     MVI    L,4
  717.     CALL    FCBPAD
  718.  
  719.     LXI    H,16            ; fp[16] = 0;
  720.     DAD    B
  721.     MVI    M,0
  722.  
  723.     RET                ; return;
  724. ;
  725. ;    fcbfill(dest,name,pad,size)
  726. ;        B    D    H   L
  727. ;
  728. FCBFILL:
  729.     MOV    A,L            ; while(L>0 && (A= *D)~='.' && A~=0){
  730.     ORA    A
  731.     JZ    FILL2
  732.     LDAX    D
  733.     CPI    '.'
  734.     JZ    FILL2
  735.     CPI    0
  736.     JZ    FILL2
  737.  
  738.     CPI    61H            ;    if(A>='a' && A<='z')
  739.      JC    FILL1
  740.     CPI    7AH+1            ; 'z' 9 Jun 80 rj
  741.     JNC    FILL1
  742.  
  743.     SUI    61H-41H             ;        A = A - 'a' + 'A';
  744. FILL1:
  745.     STAX    B            ;    *B++ = A;
  746.     INX    B
  747.  
  748.     INX    D            ;    D++;
  749.  
  750.     DCR    L            ;    L--;
  751.     JMP    FCBFILL            ;    }
  752. FILL2:
  753.     LDAX    D            ; while(*D~='.' && *D~=0)    
  754.     CPI    '.'
  755.     JZ    FILL3
  756.     CPI    0
  757.     JZ    FILL3
  758.  
  759.     INX    D            ;    D++;
  760.     JMP    FILL2
  761. FILL3:
  762.     CPI    '.'            ; if(*D=='.')
  763.     JNZ    FILL4
  764.     INX    D            ;    D++;
  765. FILL4:
  766. ;    fall into...
  767. ;
  768. ;    fcbpad(dest,pad,size)
  769. ;        B   H   L
  770. ;
  771. FCBPAD:
  772.     MOV    A,L            ; while(L>0){
  773.     ORA    A
  774.     JZ    PAD2
  775.  
  776.     MOV    A,H            ;    *B++ = H;
  777.     STAX    B
  778.     INX    B
  779.  
  780.     DCR    L            ;    L--;
  781.  
  782.     JMP    FCBPAD            ;    }
  783. PAD2:
  784.     RET                ; return;
  785. ;
  786. ;    getc(unit)
  787. ;
  788. QZGETC:
  789.     POP    B
  790.     POP    H            ; get args
  791.     PUSH    H
  792.     PUSH    B
  793.                     ; c=cget(unit);
  794.     PUSH    H
  795.     CALL    CGET
  796.     POP    D
  797.  
  798.     MOV    A,L            ; if(c=='\r')     
  799.     CPI    EOL
  800.     JNZ    GETCRET
  801.  
  802.     PUSH    H            ;    cget(unit)
  803.     PUSH    D            ;        /* to absorb LF */
  804.     CALL    CGET
  805.     POP    H
  806.     POP    H
  807. GETCRET:
  808.     RET
  809. ;
  810. ;    cget(unit)
  811. ;
  812. CGET:
  813.     POP    D
  814.     POP    H
  815.     SHLD    UNIT
  816.     PUSH    H
  817.     PUSH    D
  818.  
  819.     LXI    D,FLAG            ; if(unit[FLAG] & EOF_FL)
  820.     DAD    D
  821.     MOV    A,M
  822.     ANI    EOFFLG
  823.     JZ    GETCIF1
  824.  
  825.     LXI    H,-1            ;    return(-1);
  826.     RET
  827. GETCIF1:
  828.     LHLD    UNIT            ; ip = unit + FCBSIZE;
  829.     LXI    D,FCBSIZE
  830.     DAD    D
  831.     SHLD    IP
  832.  
  833.     LXI    D,NEXTP            ; cp = ip[NEXTP];
  834.     DAD    D
  835.     MOV    E,M
  836.     INX    H
  837.     MOV    D,M
  838.     XCHG
  839.     SHLD    CHP
  840.  
  841.     LHLD    IP            ; if(ip[UNUSED]==0){
  842.     LXI    D,UNUSED
  843.     DAD    D
  844.  
  845.     MOV    A,M
  846.     INX    H
  847.     ORA    M
  848.     JNZ    GETCIF2
  849.  
  850.     LXI    H,READ            ;    if(cpmio(READ,unit)~=0)
  851.      PUSH    H
  852.     LHLD    UNIT
  853.     PUSH    H
  854.     CALL    CPMIO
  855.     POP    D
  856.     POP    D
  857.     MOV    A,H
  858.     ORA    L
  859.     JZ    GETCIF3
  860.  
  861.     LXI    H,-1            ;        return(-1);
  862.     RET
  863. GETCIF3:
  864.     LHLD    IP            ;    else {    ip[UNUSED] = BUFSIZ;
  865.     LXI    D,UNUSED
  866.     DAD    D
  867.     LXI    D,BUFSIZ
  868.     MOV    M,E
  869.     INX    H
  870.     MOV    M,D
  871.  
  872.     LHLD    IP            ;        cp = &ip[BUFFER];
  873.     LXI    D,BUFFER
  874.     DAD    D
  875.     SHLD    CHP
  876.                     ;        }
  877.                     ;    }
  878. GETCIF2:
  879.     LHLD    IP            ; ip[UNUSED]--;
  880.     LXI    D,UNUSED
  881.     DAD    D
  882.     MOV    E,M
  883.     INX    H
  884.     MOV    D,M
  885.     DCX    D
  886.     MOV    M,D
  887.     DCX    H
  888.     MOV    M,E
  889.  
  890.     LHLD    CHP            ; ip[NEXTP] = cp+1;
  891.     INX    H
  892.     XCHG
  893.     LHLD    IP
  894.     LXI    B,NEXTP
  895.     DAD    B
  896.     MOV    M,E
  897.     INX    H
  898.     MOV    M,D
  899.  
  900.     LHLD    CHP            ; if(*cp==CTRL_Z){
  901.     MOV    A,M
  902.     CPI    CTRLZ
  903.     JNZ    GETCIF4
  904.  
  905.     LHLD    UNIT            ;    unit[FLAG] |= EOF_FL;
  906.     LXI    D,FLAG
  907.     DAD    D
  908.     MOV    A,M
  909.     ORI    EOFFLG
  910.     MOV    M,A
  911.  
  912.     LXI    H,-1            ;    return(-1);
  913.     RET
  914.                     ;    }
  915. GETCIF4:
  916.     MOV    L,A            ; return(*cp & 0377);
  917.     MVI    H,0
  918.     RET
  919. ;
  920. ;    putc(c,unit)
  921. ;
  922. QZPUTC:
  923.     POP    B    ;rtn addr
  924.     POP    D    ;unit
  925.     POP    H    ;c
  926.     PUSH    H
  927.     PUSH    D
  928.     PUSH    B
  929.  
  930.     PUSH    H            ; if(cput(c,unit)<0)
  931.     PUSH    D            ;    goto putcerr;
  932.     CALL    CPUT
  933.     POP    D
  934.     MOV    A,H
  935.     ORA    A
  936.     JM    PUTCERR
  937.  
  938.     MOV    A,L            ; if(c=='\r')
  939.     CPI    EOL
  940.     JNZ    PUTCRET
  941.  
  942.     LXI    H,LF            ;    cput('\n',unit);
  943.     PUSH    H
  944.     PUSH    D
  945.     CALL    CPUT
  946.     POP    D
  947.     POP    D
  948.     MOV    A,H
  949.     ORA    A
  950.     JM    PUTCERR
  951.  
  952. PUTCRET:
  953.     POP    H            ; return(c);
  954.     RET
  955. PUTCERR:                ;putcerr:
  956.     POP    B            ; return(-1);
  957.     LXI    H,-1
  958.     RET
  959. ;
  960. ;    cput(c,unit)
  961. ;
  962. CPUT:
  963.     POP    B
  964.     POP    D
  965.     POP    H
  966.     SHLD    ZCH
  967.     XCHG
  968.     SHLD    UNIT
  969.     PUSH    D
  970.     PUSH    H
  971.     PUSH    B
  972.  
  973.     LXI    D,FCBSIZE        ; ip = unit + FCBSIZE;
  974.     DAD    D
  975.     SHLD    IP
  976.  
  977.     LXI    D,NEXTP            ; cp = ip[NEXTP];
  978.     DAD    D
  979.     MOV    E,M
  980.     INX    H
  981.     MOV    D,M
  982.     XCHG
  983.     SHLD    CHP
  984.  
  985.     LHLD    IP            ; if(ip[UNUSED]==0){
  986.     LXI    D,UNUSED
  987.     DAD    D
  988.     MOV    A,M
  989.     INX    H
  990.     ORA    M
  991.     JNZ    PUTCIF1
  992.  
  993.     LXI    H,WRITE            ;    if(cpmio(WRITE,unit)~=0)    
  994.     PUSH    H
  995.     LHLD    UNIT
  996.     PUSH    H
  997.     CALL    CPMIO
  998.     POP    D
  999.     POP    D
  1000.     MOV    A,H
  1001.     ORA    L
  1002.     JZ    PUTCIF2
  1003.  
  1004.     LXI    H,-1            ;        return(-1);
  1005.     RET
  1006. PUTCIF2:
  1007.     LHLD    IP            ;    else {    ip[UNUSED] = BUFSIZ;
  1008.     LXI    D,UNUSED
  1009.     DAD    D
  1010.     LXI    D,BUFSIZ
  1011.     MOV    M,E
  1012.     INX    H
  1013.     MOV    M,D
  1014.  
  1015.     LHLD    IP            ;        cp = &ip[BUFFER];
  1016.     LXI    D,BUFFER
  1017.     DAD    D
  1018.     SHLD    CHP
  1019.                     ;        }
  1020.                     ;    }
  1021. PUTCIF1:
  1022.     LHLD    IP
  1023.     LXI    D,UNUSED        ; ip[UNUSED]--;
  1024.     DAD    D
  1025.     MOV    E,M
  1026.     INX    H
  1027.     MOV    D,M
  1028.     DCX    D
  1029.     MOV    M,D
  1030.     DCX    H
  1031.     MOV    M,E
  1032.  
  1033.     LHLD    CHP            ; ip[NEXTP] = cp+1;
  1034.     INX    H
  1035.     XCHG
  1036.     LHLD    IP
  1037.     LXI    B,NEXTP
  1038.     DAD    B
  1039.     MOV    M,E
  1040.     INX    H
  1041.     MOV    M,D
  1042.  
  1043.     LDA    ZCH            ; return((*cp = c) & 0377);
  1044.     LHLD    CHP
  1045.     MOV    M,A
  1046.     MVI    H,0
  1047.     MOV    L,A
  1048.     RET
  1049. ;
  1050. ;    gets(buff)
  1051. ;
  1052. QZGETS:
  1053.     POP    B
  1054.     POP    H
  1055.     SHLD    CHP
  1056.     PUSH    H
  1057.     PUSH    B
  1058.  
  1059.     DCX    H            ; save = buff[-1]; save2 = buff[-2];
  1060.     MOV    D,M            ; buff[-1] = 0;  buff[-2] = 79;
  1061.     MVI    M,0
  1062.     DCX    H
  1063.     MOV    E,M
  1064.     MVI    M,79                    ;6 May 80 rj
  1065.     PUSH    H
  1066.     PUSH    D
  1067.  
  1068.     XCHG                ; cpm(GETSTR,buff-2);
  1069.     MVI    C,GETSTR
  1070.     CALL    BDOS
  1071.  
  1072.     LHLD    CHP            ; buff[buff[-1]] = 0; (9 Jun 80. Was cp)
  1073.     DCX    H
  1074.     MOV    E,M
  1075.     INX    H
  1076.     MVI    D,0
  1077.     DAD    D
  1078.     MVI    M,0
  1079.  
  1080.     POP    D            ; buff[-1] = save; buff[-2] = save2;
  1081.     POP    H
  1082.     MOV    M,E
  1083.     INX    H
  1084.     MOV    M,D
  1085.     INX    H
  1086.  
  1087.     MVI    C,PUTCH            ; putchar('\n');
  1088.     MVI    E,LF
  1089.     CALL    BDOS
  1090.  
  1091.     LHLD    CHP            ; return(buff);
  1092.     RET
  1093. ;
  1094. ;    getchar()
  1095. ;
  1096. QZGETCHAR:
  1097.     MVI    C,GETCH            ; t = cpm(GETCH,0) & 0377;
  1098.     CALL    BDOS
  1099.     MOV    L,A         
  1100.     MVI    H,0
  1101.  
  1102.     CPI    CTRLZ            ; if(t==CTRLZ)
  1103.     JNZ    GETCHAR1
  1104.  
  1105.     LXI    H,-1            ;    t = -1;
  1106. GETCHAR1:
  1107.     CPI    EOL            ; if(t==EOL)
  1108.     JNZ    GETCHAR2
  1109.  
  1110.     PUSH    H            ;    putchar('\n');
  1111.     MVI    C,PUTCH
  1112.     MVI    E,LF
  1113.     CALL    BDOS
  1114.     POP    H
  1115. GETCHAR2:
  1116.     RET                ; return(t);
  1117. ;
  1118. ;    puts(cp)
  1119. ;
  1120. QZPUTS:
  1121.     POP    B            ; get args
  1122.     POP    H
  1123.     PUSH    H
  1124.     PUSH    B
  1125. PUTS1:
  1126.     MOV    A,M            ; while(*cp)
  1127.     ORA    A
  1128.     JZ    PUTSRET
  1129.  
  1130.     MOV    E,M            ;    putchar(*cp++);
  1131.     INX    H
  1132.     PUSH    H
  1133.     MVI    C,PUTCH
  1134.     CALL    BDOS
  1135.     POP    H
  1136.     JMP    PUTS1
  1137.  
  1138. PUTSRET:
  1139.     RET                ; return;
  1140. ;
  1141. ;    putchar(c)
  1142. ;
  1143. QZPUTCHAR:
  1144.     POP    B
  1145.     POP    H
  1146.     SHLD    ZCH
  1147.     PUSH    H
  1148.     PUSH    B
  1149.  
  1150.     XCHG                ; cpm(PUTCH,c);
  1151.     MVI    C,PUTCH
  1152.     CALL    BDOS
  1153.  
  1154.     LDA    ZCH            ; if(c==EOL)
  1155.     CPI    EOL
  1156.     JNZ    PUTCHIF1
  1157.  
  1158.     MVI    E,LF            ;    cpm(PUTCH,LF);
  1159.     MVI    C,PUTCH
  1160.     CALL    BDOS
  1161. PUTCHIF1:
  1162.     LHLD    ZCH            ; return(c & 0377);
  1163.     MVI    H,0
  1164.     RET
  1165. ;
  1166. ;    cpmio(fn,unit)
  1167. ;
  1168. CPMIO:
  1169.     POP    B
  1170.     POP    D
  1171.     POP    H
  1172.     SHLD    FN
  1173.     XCHG
  1174.     SHLD    UNIT
  1175.     PUSH    D
  1176.     PUSH    H
  1177.     PUSH    B
  1178.  
  1179.     LHLD    UNIT            ; cpmdisk(*unit);
  1180.     MOV    L,M
  1181.     MVI    H,0
  1182.     PUSH    H
  1183.     CALL    CPMDISK
  1184.     POP    H
  1185.  
  1186.     LHLD    UNIT            ; ip = unit+FCBSIZE;
  1187.     LXI    D,FCBSIZE        ; cpm(DMA,&ip[BUFFER]);
  1188.     DAD    D
  1189.     LXI    D,BUFFER
  1190.     DAD    D
  1191.     XCHG
  1192.     MVI    C,DMA
  1193.     CALL    BDOS
  1194.  
  1195.     LHLD    FN            ; t = cpm(fn,unit);
  1196.     MOV    C,L
  1197.     LHLD    UNIT
  1198.     XCHG
  1199.     CALL    BDOS
  1200.     CALL    CCSXT
  1201.     SHLD    ZT
  1202.  
  1203.     MVI    C,DMA            ; cpm(DMA,TBUFF);
  1204.     LXI    D,TBUFF
  1205.     CALL    BDOS
  1206.  
  1207.     LHLD    ZT            ; if(t~=0) return(-1);
  1208.     MOV    A,H            ; else       return(0);
  1209.     ORA    L
  1210.     JNZ    CPMIF1
  1211.     LXI    H,0
  1212.     JMP    CPMIF2
  1213. CPMIF1:
  1214.     LXI    H,-1
  1215. CPMIF2:
  1216.     RET
  1217. ;
  1218. ;    cpmdisk(disk)
  1219. ;
  1220. CPMDISK:
  1221.     POP    D
  1222.     POP    H
  1223.     PUSH    H
  1224.     PUSH    D
  1225.  
  1226.     MOV    A,L            ; if(d~=0)
  1227.     ORA    H
  1228.     JZ    DISKIF1
  1229.  
  1230.     XCHG                ;    cpm(SELECT,d-1);
  1231.     DCX    D
  1232.     MVI    C,SELECT
  1233.     CALL    BDOS
  1234. DISKIF1:
  1235.     RET
  1236. ;
  1237. ;----------- End of Small-c library -----------
  1238. ;
  1239. #endasm
  1240.  
  1241.